<?php

/*
	This file is part of Core. Copyright © 2007, Emanuele Vulcano.

	Core is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	Core is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Core; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
	
*/

global $_CAutoInclude;
$_CAutoInclude = array();

if (!CIsPHP4()) {
	function __autoload($name) {
		global $_CAutoIncludeAddOns;
		foreach ($_CAutoIncludeAddOns as $callable => $dummy) {
			if (call_user_func($callable, $name))
				return;
		}
		
		CRequireOne($name);
	}
}

/**
	Registers classes so that the built-in autoload function and CRequire() variants can load them.
	
	@param files An array whose keys are file names, and whose values are arrays of class names. For example: array ('a.php' => array('ClassA', 'ClassB')).
	@param prefix If specified, it is prepended to all file names in the files array. If it doesn't end with a directory separator character, the directory separator character will be appended to it. ('/' on UNIX systems.)
*/
function CAutoIncludeRegisterClassesIn($files, $prefix = null) {
	if (!$prefix)
		$prefix = '';
	
	if (strlen($prefix) != 0 && !CHasSuffix($prefix, DIRECTORY_SEPARATOR))
		$prefix .= DIRECTORY_SEPARATOR;
	
	global $_CAutoInclude;
	
	foreach ($files as $fileName => $classes) {
		$file = $prefix . $fileName;
		if (is_string($classes))
			$_CAutoInclude[CSymbol($classes)] = $file;
		else {
			foreach ($classes as $class)
				$_CAutoInclude[CSymbol($class)] = $file;
		}
	}
}

/**
	Requires the file containing the single class given as argument to be loaded. It is usually easier to use CRequire() instead.
	
	@param class The class name as a string.
*/
function CRequireOne($class) {
	global $_CAutoInclude;
	$f = @$_CAutoInclude[CSymbol($class)];
	if (!is_null($f))
		require_once $f;
}

/**
	Requires the files containing all classes in the given array to be loaded.

	@param arr An array of class name.
*/
function CRequireAll($arr) {
	foreach ($arr as $class)
		CRequireOne($class);
}

/**
Loads all files that aren't loaded already and that contain
the CAutoInclude-registered classes whose names are specified
as arguments.

@param class... The classes to load as separate argument strings.
*/
function CRequire($class /* ... */) {
	$a = func_get_args();
	CRequireAll($a);
}

/**
Loads all files containing the classes given as arguments, but only if the
interpreter is PHP 4. This is useful as it allows code to load
classes declaratively in PHP 4 while still allowing PHP 5's autoload
to only load the required classes.

This is mainly useful for code that doesn't know in which environment it
will run, i.e. external kits.

@param class... The classes to load as separate argument strings.
*/
function CRequireIfPHP4($class /* ... */) {
	$a = func_get_args();
	if (CIsPHP4()) CRequireAll($a);
}

global $_CAutoIncludeAddOns;
$_CAutoIncludeAddOns = array();

/**
Register a callable to be called as part of __autoload() in PHP 5.

As of this version, there is no way to remove a callable from __autoload() calling and there is no way to add callables to CRequire(). A callable can be safely registered multiple times, but will always be called only once.

@param callable A callable with signature 'bool ...(string $name) { }'. If it returns true, __autoload() will not do anything else; if it returns false, other callables will be called or the default CRequire() mechanism will be called instead.
*/
function CAutoIncludeRegisterAddOn($callable) {
	global $_CAutoIncludeAddOns;
	$_CAutoIncludeAddOns[CSymbol($callable)] = true; // uniqueness
}

function CRequireKit($name) {
	require_once $name . DIRECTORY_SEPARATOR . $name . '.php';
}

function CDefineKit($name, $fileClasses) {
	CAutoIncludeRegisterClassesIn($fileClasses, $name);
}

?>